package com.teen9g.infoplatformserver.service.impl;

import com.teen9g.constant.RedisKey;
import com.teen9g.entity.*;
import com.teen9g.infoplatformserver.mapper.*;
import com.teen9g.infoplatformserver.service.CommonService;
import com.teen9g.top10VO.CanteenShopTop10VO;
import com.teen9g.top10VO.MaimaiChunithmTop10VO;
import com.teen9g.top10VO.PlaygroundTop10VO;
import com.teen9g.top10VO.TeachingBuildingTop10VO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CommonServiceImpl implements CommonService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private CanteenShopMapper canteenShopMapper;

    @Autowired
    private TeachingBuildingMapper teachingBuildingMapper;

    @Autowired
    private PlaygroundMapper playgroundMapper;

    @Autowired
    private MaimaiChunithmMapper maimaiChunithmMapper;

    @Autowired
    private RecentEditMapper recentEditMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    @Override
    public Total getTotal() {
        Integer userTotal = userMapper.selectCount(null);
        Integer canteenShopTotal = canteenShopMapper.selectCount(null);
        Integer teachingBuildingTotal = teachingBuildingMapper.selectCount(null);
        Integer PlaygroundTotal = playgroundMapper.selectCount(null);
        Integer MaimaiChunithmTotal = maimaiChunithmMapper.selectCount(null);
        Integer recentEditTotal = recentEditMapper.selectCount(null);
        Integer total = canteenShopTotal + teachingBuildingTotal + PlaygroundTotal + MaimaiChunithmTotal;
        return Total.builder()
                .userTotal(userTotal)
                .canteenShopTotal(canteenShopTotal)
                .teachingBuildingTotal(teachingBuildingTotal)
                .PlaygroundTotal(PlaygroundTotal)
                .MaimaiChunithmTotal(MaimaiChunithmTotal)
                .recentEditTotal(recentEditTotal)
                .total(total)
                .build();
    }

    /**
     * 获取前10的店铺信息
     *
     * @return 前10的店铺信息
     */
    @Override
    public List<CanteenShopTop10VO> getCSTop10() {
        // 1. 获取 Top10 （按浏览量降序）
        Set<String> triples = redisTemplate.opsForZSet()
                .reverseRange(RedisKey.CS_TOP10_KEY, 0, 9);

        // 检查数据是否存在，如果不存在就从MySQL中获取数据，并存入Redis，然后封装返回
        if (triples == null || triples.isEmpty()) {
            // MySQL获取总浏览量前10的店铺
            List<CanteenShop> list = canteenShopMapper.selectTopTotalViewCanteenShops(10);
            list.forEach(canteenShop -> {
                String triple = String.format(
                        "%d|%s|%d",
                        canteenShop.getShopId(),
                        canteenShop.getShopName(),
                        canteenShop.getShopView()
                );
                redisTemplate.opsForZSet().
                        add(RedisKey.CS_TOP10_KEY,
                                triple,
                                canteenShop.getShopView()); //使用浏览量作为排序分数
            });
            return this.getCSTop10();
        }
        // 2. 解析管道三元组
        return triples.stream()
                .map(triple -> {
                    String[] parts = triple.split("\\|");
                    if (parts.length != 3) {
                        log.warn("无效三元组");
                        return null;
                    }
                    try {
                        return new CanteenShopTop10VO(
                                Integer.parseInt(parts[0]), //shopId
                                parts[1], //shopName
                                Integer.parseInt(parts[2])  //shopView
                        );
                    } catch (NumberFormatException e) {
                        log.error("解析三元组失败：{}", triple, e);
                        return null;
                    }
                })
                .filter(Objects::nonNull)  //过滤解析失败的数据
                .collect(Collectors.toList());

    }

    @Override
    public List<TeachingBuildingTop10VO> getTBTop10() {
        // 1. 获取 Top10 （按浏览量降序）
        Set<String> triples = redisTemplate.opsForZSet()
                .reverseRange(RedisKey.TB_TOP10_KEY, 0, 9);

        // 检查数据是否存在，如果不存在就从MySQL中获取数据，并存入Redis，然后封装返回
        if (triples == null || triples.isEmpty()) {
            // MySQL获取总浏览量前10的教学楼
            List<TeachingBuilding> list = teachingBuildingMapper.selectTopTotalViewTeachingBuildings(10);
            if (list == null || list.isEmpty()) {
                log.warn("获取前十浏览量的教学楼失败");
                return null;
            }
            //删除Redis中的数据
            redisTemplate.delete(RedisKey.TB_TOP10_KEY);

            //将新数据存入Redis
            list.forEach(teachingBuilding -> {
                String triple = String.format(
                        "%d|%s|%d",
                        teachingBuilding.getBuildingId(),
                        teachingBuilding.getContentTitle(),
                        teachingBuilding.getContentView()
                );
                redisTemplate.opsForZSet().
                        add(RedisKey.TB_TOP10_KEY,
                                triple,
                                teachingBuilding.getContentView()); //使用浏览量作为排序分数
            });
            return this.getTBTop10();
        }

        // 2. 解析管道三元组
        return triples.stream()
                .map(triple -> {
                    String[] parts = triple.split("\\|");
                    if (parts.length != 3) {
                        log.warn("无效三元组");
                        return null;
                    }
                    try {
                        return new TeachingBuildingTop10VO(
                                Integer.parseInt(parts[0]), //contentId
                                parts[1], //contentTitle
                                Integer.parseInt(parts[2])  //contentView
                        );
                    } catch (NumberFormatException e) {
                        log.error("解析三元组失败：{}", triple, e);
                        return null;
                    }
                })
                .filter(Objects::nonNull)  //过滤解析失败的数据
                .collect(Collectors.toList());

    }

    @Override
    public List<PlaygroundTop10VO> getPLTop10() {
        // 1.获取Top10 按浏览量降序）
        Set<String> triples = redisTemplate.opsForZSet()
                .reverseRange(RedisKey.PL_TOP10_KEY, 0, 9);
        // 检查数据是否存在，如果不存在就从MySQL中获取数据，并存入Redis，然后封装返回
        if (triples == null || triples.isEmpty()) {
            // MySQL获取总浏览量前10的运动场
            List<Playground> list = playgroundMapper.selectTopTotalViewPlaygrounds(10);
            if (list == null || list.isEmpty()) {
                log.warn("获取前十浏览量的运动场失败");
                return null;
            }
            //删除Redis中的数据
            redisTemplate.delete(RedisKey.PL_TOP10_KEY);
            //将新数据存入Redis
            list.forEach(playground -> {
                String triple = String.format(
                        "%d|%s|%d",
                        playground.getContentId(),
                        playground.getContentTitle(),
                        playground.getPlaygroundView()
                );
                redisTemplate.opsForZSet().
                        add(RedisKey.PL_TOP10_KEY,
                                triple,
                                playground.getPlaygroundView()); //使用浏览量作为排序分数
            });
            return this.getPLTop10();
        }

        // 2.解析管道三元组
        return triples.stream()
                .map(triple -> {
                    String[] parts = triple.split("\\|");
                    if (parts.length != 3) {
                        log.warn("无效三元组");
                        return null;
                    }
                    try {
                        return new PlaygroundTop10VO(
                                Integer.parseInt(parts[0]), //contentId
                                parts[1], //contentTitle
                                Integer.parseInt(parts[2])  //playgroundView
                        );
                    } catch (NumberFormatException e) {
                        log.error("解析三元组失败：{}", triple, e);
                        return null;
                    }
                })
                .filter(Objects::nonNull)  //过滤解析失败的数据
                .collect(Collectors.toList());
    }

    @Override
    public List<MaimaiChunithmTop10VO> getMCTop10() {
        // 1.获取Top10 按浏览量降序）
        Set<String> triples = redisTemplate.opsForZSet()
                .reverseRange(RedisKey.MC_TOP10_KEY, 0, 9);
        // 检查数据是否存在，如果不存在就从MySQL中获取数据，并存入Redis，然后封装返回
        if (triples == null || triples.isEmpty()) {
            // MySQL获取总浏览量前10的舞萌中二
            List<MaimaiChunithm> list = maimaiChunithmMapper.selectTopTotalViewMaimaiChunithms(10);
            if (list == null || list.isEmpty()) {
                log.warn("获取前十浏览量的舞萌中二失败");
                return null;
            }
            //删除Redis中的数据
            redisTemplate.delete(RedisKey.MC_TOP10_KEY);
            //将新数据存入Redis
            list.forEach(maimaiChunithm -> {
                String triple = String.format(
                        "%d|%s|%d",
                        maimaiChunithm.getContentId(),
                        maimaiChunithm.getShopName(),
                        maimaiChunithm.getContentView()
                );
                redisTemplate.opsForZSet()
                        .add(RedisKey.MC_TOP10_KEY,
                                triple,
                                maimaiChunithm.getContentView());
            });
            return this.getMCTop10();
        }
        // 2.解析管道三元组
        return triples.stream()
                .map(triple -> {
                    String[] parts = triple.split("\\|");
                    if (parts.length != 3) {
                        log.warn("无效三元组");
                    }
                    try {
                        return new MaimaiChunithmTop10VO(
                                Integer.parseInt(parts[0]), //contentId
                                parts[1], //contentTitle
                                Integer.parseInt(parts[2])  //contentView
                        );
                    } catch (NumberFormatException e) {
                        log.error("解析三元组失败：{}", triple, e);
                        return null;
                    }
                })
                .filter(Objects::nonNull)  //过滤解析失败的数据
                .collect(Collectors.toList());
    }
}
